package com.lucifer.cloud.boot.blog.service.impl;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lucifer.cloud.boot.blog.domin.type.ArticleQueryType;
import com.lucifer.cloud.boot.blog.domin.type.BlogConstant;
import com.lucifer.cloud.boot.blog.domin.type.BlogStatusType;
import com.lucifer.cloud.boot.blog.domin.type.BlogType;
import com.lucifer.cloud.boot.blog.domin.type.CategoryType;
import com.lucifer.cloud.boot.blog.config.UserSystem;
import com.lucifer.cloud.boot.blog.domin.bo.Article;
import com.lucifer.cloud.boot.blog.domin.bo.Comment;
import com.lucifer.cloud.boot.blog.domin.bo.Follow;
import com.lucifer.cloud.boot.blog.domin.bo.Likes;
import com.lucifer.cloud.boot.blog.domin.bo.Star;
import com.lucifer.cloud.boot.blog.domin.bo.User;
import com.lucifer.cloud.boot.blog.domin.dto.article.ArticleConverter;
import com.lucifer.cloud.boot.blog.domin.dto.article.ArticleDto;
import com.lucifer.cloud.boot.blog.domin.dto.article.ArticleReq;
import com.lucifer.cloud.boot.blog.domin.dto.user.UserConverter;
import com.lucifer.cloud.boot.blog.domin.dto.user.UserInfo;
import com.lucifer.cloud.boot.blog.mapper.ArticleMapper;
import com.lucifer.cloud.boot.blog.mapper.CommentMapper;
import com.lucifer.cloud.boot.blog.mapper.FollowMapper;
import com.lucifer.cloud.boot.blog.mapper.LikesMapper;
import com.lucifer.cloud.boot.blog.mapper.StarMapper;
import com.lucifer.cloud.boot.blog.mapper.UserMapper;
import com.lucifer.cloud.boot.blog.service.ArticleService;
import com.lucifer.cloud.commons.model.Result;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lucifer
 * @date 2023/12/21 15:24
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Resource
    private UserSystem userSystem;

    @Resource
    private UserMapper userMapper;

    @Resource
    private CommentMapper commentMapper;

    @Resource
    private StarMapper starMapper;

    @Resource
    private FollowMapper followMapper;

    @Resource
    private LikesMapper  likesMapper;

    @Override
    public ArticleDto info(HttpServletRequest request,String uid,String user_id, Integer page, Integer limit,  String sort,String queryType,Integer category) {
        Long userId = userSystem.userId(request);
        if(ArticleQueryType.DETAIL.getCode().equals(queryType) && Objects.nonNull(user_id)){
            userId = Long.parseLong(user_id);
        }
        User user = userMapper.selectById(userId);
        UserInfo user_info = UserConverter.convertInfo(user);

        Long count = 0L;

        List<Article> articleList = Lists.newArrayList();
        if(Objects.isNull(page) && Objects.isNull(limit)){
            articleList = list(Wrappers.lambdaQuery(Article.class)
                    .eq(StringUtils.isBlank(uid) && (Objects.nonNull(userId) && Objects.equals(CategoryType.MY.getIndex(), category)) , Article::getUser_id, userId)
                    .eq(  StringUtils.isBlank(uid) &&  (Objects.isNull(userId) || !Objects.equals(CategoryType.MY.getIndex(), category)) ,Article::getStatus, BlogStatusType.OPEN.getIndex())
                    .eq(StringUtils.isNotBlank(uid),Article::getUid,uid)
                    .last(StringUtils.isNotBlank(sort), "order by " + sort));
            count = articleList.stream().count();
        }else {
            Page<Article> rowPage = new Page<>(page, limit);
            Page<Article> articlePage = this.baseMapper.selectPage(rowPage,Wrappers.lambdaQuery(Article.class)
                    .eq(StringUtils.isBlank(uid) && Objects.nonNull(userId) && Objects.equals(CategoryType.MY.getIndex(), category), Article::getUser_id, userId)
                    .eq(  StringUtils.isBlank(uid) && Objects.isNull(userId) || !Objects.equals(CategoryType.MY.getIndex(), category) ,Article::getStatus, BlogStatusType.OPEN.getIndex())
                    .eq(StringUtils.isNotBlank(uid),Article::getUid,uid)
                    .last(StringUtils.isNotBlank(sort),"order by "+ sort)
            );
            articleList = articlePage.getRecords();
            count = articlePage.getTotal();
        }

        List<Comment> commentList = commentMapper.selectList(Wrappers.lambdaQuery(Comment.class)
                .eq(Comment::getType, BlogType.ARTICLE.getCode())
                .eq(StringUtils.isNotBlank(uid),Comment::getContent_id,uid)
        );
        List<Star> starList = starMapper.selectList(Wrappers.lambdaQuery(Star.class)
                .eq(Star::getType, BlogType.ARTICLE.getIndex())
                .eq(StringUtils.isNotBlank(uid), Star::getStar_id,uid)
                .eq(Star::getStar_type,Boolean.TRUE)
        );



        List<Follow>  followList = followMapper.selectList(Wrappers.lambdaQuery(Follow.class)
                //.eq(Objects.nonNull(userId),Follow::getFollow_user_id, userId)
                .eq(Follow::getFollow_type,Boolean.TRUE));


        List<Likes>  likesList = likesMapper.selectList(Wrappers.lambdaQuery(Likes.class)
                .eq(Likes::getType, BlogType.ARTICLE.getIndex())
                .eq(StringUtils.isNotBlank(uid), Likes::getLikes_id,uid)
                .eq(Likes::getLikes_type,Boolean.TRUE));

        List<Article> articles = list(Wrappers.lambdaQuery(Article.class)
                .eq(Objects.nonNull(userId), Article::getUser_id, userId)
        );

        List<User> userList = Lists.newArrayList();
        if(Objects.isNull(userId) || !Objects.equals(CategoryType.MY.getIndex(), category)){
            List<Long> userIdList = Optional.ofNullable(articleList).orElse(Lists.newArrayList())
                    .stream().map(Article::getUser_id)
                    .collect(Collectors.toList());
            userList = userMapper.selectList(Wrappers.lambdaQuery(User.class).in(userIdList.size() > 0,User::getId, userIdList));
        }


        return ArticleConverter.converter2Dto(articleList, count, user_info,userId,commentList,starList,followList,likesList, articles,userList,category);
    }

    @Override
    public Result create(HttpServletRequest request, ArticleReq articleReq) {
        Long userId = userSystem.userId(request);
        if(Objects.isNull(userId)){
            return Result.error(HttpStatus.UNAUTHORIZED.value(), BlogConstant.NOT_LOGIN);
        }
        Article article = ArticleConverter.converterReq2Article(articleReq,userId);
        boolean save = save(article);
        return Result.success(save);
    }

    @Override
    public Result update(HttpServletRequest request, ArticleReq articleReq) {
        Long userId = userSystem.userId(request);
        if(Objects.isNull(userId)){
            return Result.error(HttpStatus.UNAUTHORIZED.value(), BlogConstant.NOT_LOGIN);
        }
        boolean update = update(Wrappers.lambdaUpdate(Article.class)
                .set(Article::getUpdated_at, LocalDateTime.now())
                .set(Article::getTitle, articleReq.getTitle())
                .set(Article::getSub_title, articleReq.getSub_title())
                .set(Article::getContent, articleReq.getContent())
                .eq(Article::getUid, articleReq.getUid())
        );
        return Result.success(update);
    }

    @Override
    public Result delete(HttpServletRequest request, String uid) {
        Long userId = userSystem.userId(request);
        if(Objects.isNull(userId)){
            return Result.error(HttpStatus.UNAUTHORIZED.value(), BlogConstant.NOT_LOGIN);
        }
        boolean remove = remove(Wrappers.lambdaQuery(Article.class).eq(Article::getUid, uid).eq(Objects.nonNull(userId),Article::getUser_id, userId));
        if (remove){
            commentMapper.delete(Wrappers.lambdaQuery(Comment.class).eq(Comment::getContent_id,uid).eq(Objects.nonNull(userId),Comment::getUser_id,userId));
            starMapper.delete(Wrappers.lambdaQuery(Star.class).eq(Star::getStar_id,uid).eq(Objects.nonNull(userId),Star::getUser_id,userId));
        }
        return Result.success(remove);
    }
}
